package com.freeLearning.boot.course.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.freeLearning.boot.common.enums.AuditStatusEnum;
import com.freeLearning.boot.common.result.Result;
import com.freeLearning.boot.core.security.util.SecurityUtils;
import com.freeLearning.boot.course.enums.StatusEnum;
import com.freeLearning.boot.course.mapper.CounselLogMapper;
import com.freeLearning.boot.course.mapper.CourseLikeMapper;
import com.freeLearning.boot.course.model.entity.*;
import com.freeLearning.boot.course.service.CourseAuditService;
import com.freeLearning.boot.course.service.CourseInfoService;
import com.freeLearning.boot.course.service.CourseReviewService;
import com.freeLearning.boot.system.model.entity.ConsultantAudit;
import com.freeLearning.boot.system.model.entity.ConsultantReview;
import com.freeLearning.boot.system.service.ConsultantAuditService;
import com.freeLearning.boot.system.service.ConsultantReviewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Tag(name = "28.首页信息获取接口")
@RequestMapping("/api/v1/dashboard/info")
@RestController
@RequiredArgsConstructor
public class DashboardInfoController {
    private final CourseInfoService courseInfoService;
    private final CounselLogMapper counselLogMapper;
    private final CourseReviewService courseReviewService;
    private final CourseLikeMapper courseLikeMapper;
    private final ConsultantAuditService consultantAuditService;
    private final CourseAuditService courseAuditService;
    private final ConsultantReviewService consultantReviewService;

    @Operation(summary = "获取首页卡片信息")
    @GetMapping("/geInfo")
    public Result<Map<String, Object>> getInfo() {
        Long userId = SecurityUtils.getUserId();
        Map<String,Object> map = new HashMap<>();
        // 课程数量
        long courseCount = courseInfoService.count(new LambdaQueryWrapper<CourseInfo>().eq(CourseInfo::getConsultantId, userId));
        map.put("courseCount", courseCount);
        // 咨询数量
        int size = counselLogMapper.selectList(new LambdaQueryWrapper<CounselLog>().eq(CounselLog::getConsultantId, userId)).size();
        map.put("counselCount", size);
        // 查询今天的咨询数量
        Long todayCounselCount = counselLogMapper.selectCount(new LambdaQueryWrapper<CounselLog>()
                .eq(CounselLog::getConsultantId, userId)
                .ge(CounselLog::getCounselTime, LocalDateTime.now().toLocalDate().atStartOfDay())
                .le(CounselLog::getCounselTime, LocalDateTime.now().toLocalDate().atTime(23, 59, 59))
        );
        // 咨询数量与昨天相比增长量
        map.put("counselCount", todayCounselCount);

        // 查询昨天的咨询数量
        Long yesterdayCounselCount = counselLogMapper.selectCount(new LambdaQueryWrapper<CounselLog>()
                .eq(CounselLog::getConsultantId, userId)
                .ge(CounselLog::getCounselTime, LocalDateTime.now().minusDays(1).toLocalDate().atStartOfDay())
                .le(CounselLog::getCounselTime, LocalDateTime.now().minusDays(1).toLocalDate().atTime(23, 59, 59))
        );

        // 计算增长量
        Long counselGrowth = todayCounselCount - yesterdayCounselCount;
        map.put("counselGrowth", counselGrowth);

        // 计算增长比
        double counselGrowthRate;
        if (yesterdayCounselCount == 0) {
            // 如果昨天的咨询数量为 0，增长比设为无穷大或特定值
            counselGrowthRate = Double.POSITIVE_INFINITY;
        } else {
            counselGrowthRate = (double) counselGrowth / yesterdayCounselCount;
        }
        map.put("counselGrowthRate", counselGrowthRate);
        // 课程评论总数量
        long courseReviewCount = courseReviewService.count(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getConsultantId, userId)
                .eq(CourseReview::getStatus, StatusEnum.AUDIT_PASS.getValue())
        );
        map.put("courseReviewCount", courseReviewCount);
        // 课程评论5星总数量
        long courseReviewGoodCount = courseReviewService.count(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getConsultantId, userId)
                .eq(CourseReview::getStatus, StatusEnum.AUDIT_PASS.getValue())
                .eq(CourseReview::getRating, 5)
        );
        // 好评率
        // 好评率
        double courseGoodRate = courseReviewCount == 0L ? 0.0 : (double) courseReviewGoodCount / courseReviewCount;
        BigDecimal formattedGoodRate = new BigDecimal(courseGoodRate).setScale(2, RoundingMode.HALF_UP);
        map.put("courseGoodRate", formattedGoodRate.doubleValue());
        // 课程平均分
        double courseAverageRating = 0.0;
        List<CourseReview> courseReviews = courseReviewService.list(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getConsultantId, userId)
                .eq(CourseReview::getStatus, StatusEnum.AUDIT_PASS.getValue())
        );
        if (!courseReviews.isEmpty()) {
            long totalRating = courseReviews.stream()
                    .mapToLong(CourseReview::getRating)
                    .sum();
            courseAverageRating = (double) totalRating / courseReviews.size();
        }
        BigDecimal formattedCourseAverageRating = new BigDecimal(courseAverageRating).setScale(2, RoundingMode.HALF_UP);
        map.put("courseAverageRating", formattedCourseAverageRating);
        return Result.success(map);
    }

    @Operation(summary = "获取课程获赞情况")
    @GetMapping("/geCourseLikeInfo")
    public Result<Map<String, Object>> geCourseLikeInfo() {
        Long userId = SecurityUtils.getUserId();
        List<CourseInfo> list = courseInfoService.list(new LambdaQueryWrapper<CourseInfo>()
                .eq(CourseInfo::getConsultantId, userId)
                .eq(CourseInfo::getStatus, StatusEnum.PUBLISH.getValue())
        );
        Map<String, Object> map = new HashMap<>();
        AtomicLong likeTotal = new AtomicLong(0L);
        List<Map<String,Object>> courseLikeList = new ArrayList<>();
        list.forEach(item->{
            Long likeNum = courseLikeMapper.selectCount(new LambdaQueryWrapper<CourseLike>().eq(CourseLike::getCourseId, item.getId()));
            likeTotal.addAndGet(likeNum);
            Map<String,Object> courseLikeMap = new HashMap<>();
            courseLikeMap.put("courseName",item.getTitle());
            courseLikeMap.put("likeNum",likeNum);
            courseLikeList.add(courseLikeMap);
        });
        map.put("likeTotal",likeTotal);
        map.put("courseLikeList",courseLikeList);
        return Result.success(map);
    }
    @Operation(summary = "根据起止日期查询每天的咨询数量")
    @GetMapping("/counselCountByDateRange")
    public Result<List<Map<String, Object>>> getCounselCountByDateRange(
            @RequestParam("startDate") String startDate,
            @RequestParam("endDate") String endDate) {
        // 获取当前用户ID
        Long userId = SecurityUtils.getUserId();

        // 将字符串日期转换为 LocalDate
        LocalDate startLocalDate = LocalDate.parse(startDate);
        LocalDate endLocalDate = LocalDate.parse(endDate);

        // 查询指定日期范围内的所有咨询记录
        List<CounselLog> counselLogs = counselLogMapper.selectList(new LambdaQueryWrapper<CounselLog>()
                .eq(CounselLog::getConsultantId, userId)
                .ge(CounselLog::getCounselTime, startLocalDate.atStartOfDay())
                .le(CounselLog::getCounselTime, endLocalDate.atTime(23, 59, 59))
        );

        // 按日期分组并统计每天的咨询数量
        Map<LocalDate, Long> dailyCounselCount = counselLogs.stream()
                .map(log -> log.getCounselTime().toLocalDate())
                .collect(Collectors.groupingBy(date -> date, Collectors.counting()));

        // 生成日期范围内的每一天，并填充咨询数量
        List<Map<String, Object>> result = new ArrayList<>();
        for (LocalDate date = startLocalDate; !date.isAfter(endLocalDate); date = date.plusDays(1)) {
            Map<String, Object> dailyData = Map.of(
                    "date", date.toString(),
                    "counselCount", dailyCounselCount.getOrDefault(date, 0L)
            );
            result.add(dailyData);
        }

        return Result.success(result);
    }

    @Operation(summary = "adminDashboardInfo")
    @GetMapping("/adminDashboardInfo")
    public Result<Map<String, Object>> adminDashboardInfo() {
        Long userId = SecurityUtils.getUserId();
        Map<String, Object> map = new HashMap<>();
        long pendingCounselorCount = consultantAuditService.count(new LambdaQueryWrapper<ConsultantAudit>()
                .eq(ConsultantAudit::getStatus, AuditStatusEnum.WAIT_AUDIT.getValue())
        );
        map.put("pendingCounselorCount", pendingCounselorCount);
        long approvedCounselorCount = consultantAuditService.count(new LambdaQueryWrapper<ConsultantAudit>()
                .eq(ConsultantAudit::getAuditorId, userId)
                .eq(ConsultantAudit::getStatus, AuditStatusEnum.AUDIT_PASS.getValue())
                .or()
                .eq(ConsultantAudit::getStatus, AuditStatusEnum.AUDIT_NOT_PASS.getValue())

        );
        map.put("approvedCounselorCount", approvedCounselorCount);
        long pendingCourseCount = courseAuditService.count(new LambdaQueryWrapper<CourseAudit>()
                .eq(CourseAudit::getAuditorId, userId)
                .eq(CourseAudit::getStatus, AuditStatusEnum.WAIT_AUDIT.getValue())
        );
        map.put("pendingCourseCount", pendingCourseCount);
        long approvedCourseCount = courseAuditService.count(new LambdaQueryWrapper<CourseAudit>()
                .eq(CourseAudit::getAuditorId, userId)
                .eq(CourseAudit::getStatus, StatusEnum.AUDIT_PASS.getValue())
                .or()
                .eq(CourseAudit::getStatus, StatusEnum.AUDIT_NOT_PASS.getValue())
                .or()
                .eq(CourseAudit::getStatus, StatusEnum.PUBLISH.getValue())
                .or()
                .eq(CourseAudit::getStatus, StatusEnum.WAIT_PUBLISH.getValue())
        );
        map.put("approvedCourseCount", approvedCourseCount);
        long pendingCommentCount = courseReviewService.count(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getStatus, AuditStatusEnum.WAIT_AUDIT.getValue()));
        map.put("pendingCommentCount", pendingCommentCount);
        long approvedCommentCount = courseReviewService.count(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getStatus, AuditStatusEnum.AUDIT_PASS.getValue())
                .or()
                .eq(CourseReview::getStatus, AuditStatusEnum.AUDIT_NOT_PASS.getValue())
        );
        map.put("approvedCommentCount", approvedCommentCount);
        long pendingReviewCount = consultantReviewService.count(new LambdaQueryWrapper<ConsultantReview>()
                .eq(ConsultantReview::getStatus, AuditStatusEnum.WAIT_AUDIT.getValue())
        );
        map.put("pendingReviewCount", pendingReviewCount);
        long approvedReviewCount = courseReviewService.count(new LambdaQueryWrapper<CourseReview>()
                .eq(CourseReview::getStatus, AuditStatusEnum.AUDIT_PASS.getValue())
                .or()
                .eq(CourseReview::getStatus, AuditStatusEnum.AUDIT_NOT_PASS.getValue())
        );
        map.put("approvedReviewCount", approvedReviewCount);
        return Result.success(map);
    }
}
